package com.ruoyi.ucenter.auth;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Check;
import com.ruoyi.framework.web.exception.ErrorCodeException;
import com.ruoyi.framework.web.exception.ResultCode;
import com.ruoyi.model.auth.AuthContextHolder;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.util.Optional;

@Component
public class UserLoginInterceptor implements HandlerInterceptor {

    @Resource
    private RedisCache redisCache;

    public UserLoginInterceptor(RedisCache redisCache) {
        this.redisCache = redisCache;
    }

    public UserLoginInterceptor() {
        super();
    }

    /**
     * 请求之前
     *
     * @param request  请求
     * @param response 响应
     * @param handler  处理器
     * @return 布尔
     * @throws Exception 异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        return this.getUserLoginVo(request, response, handler);
    }


    private boolean getUserLoginVo(HttpServletRequest request, HttpServletResponse response, Object handler) {
        System.err.println("测试是否进入了此处拦截器");
        Optional<Check> authCheck = this.getAuthCheck(handler, Check.class);
        if (!authCheck.isPresent()) { //如果Optional的返回值是空 说明方法上没有加注解 直接放行不需要校验
            return true;
        } else {
            String token = request.getHeader("token");
            if (StringUtils.isEmpty(token)) {
                throw new ErrorCodeException(ResultCode.FAIL_SIGN_IN, "用户未登录");
            }
            if (!authCheck.get().required()) {
                //这种情况说明 用户进入了一个 不需要登录就可以访问的页面 但是只有细节看不到
                return true;
            }
            try {
                Claims claims = JwtUtil.parseJWT(token);
                String json = claims.getSubject();
                String userId = JSONObject.parseObject(json, String.class);
                //引入AuthContextHolder工具类
                AuthContextHolder.setUserId(userId);
                AuthContextHolder.setUserInfo(redisCache.getCacheObject("loginUser:" + userId));
            } catch (Exception e) {
                throw new ErrorCodeException(ResultCode.FAIL_SIGN_IN, "非法登录");
            }
        }
        return true;
    }


    /**
     * 校验注解
     *
     * @param handler 处理器
     * @return 是否存在注解
     */
    private <A extends Annotation> Optional<A> getAuthCheck(Object handler, Class<A> anno) {
        if (handler instanceof HandlerMethod) { //专享
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //查看方法中是否有注解
            A annotation = handlerMethod.getMethod().getAnnotation(anno);
            if (annotation == null) {
                return Optional.empty();
            }
            return Optional.of(annotation);
        }
        return Optional.empty();
    }
}